package com.hejing.io流概述.FileStream;

import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * ClassName: FileReaderWriterTest
 * Package: com.hejing.io流概述.FileStream
 * Description:
 *
 * @Author: HeJing
 * @Create: 2023-05-31 20:22
 * @Version: 1.0
 */
public class FileReaderWriterTest {

    /**
     * 需求: 读取文件 D:\HeJing_Java\io_test\hello.txt 中的内容
     * <p>
     * 异常使用 throws的方式不太合适(因为涉及到了 资源的关闭close()操作。)，具体解决方法见 test02
     */
    @Test
    public void test01() throws IOException {

        // 1、创建File类的对象，对应着hello.txt文件
        File file = new File("D:\\HeJing_Java\\io_test\\hello.txt");
        // 2、创建输入型的字符流，用于读取数据。
        FileReader fr = new FileReader(file);
        // 3、读取数据，并显示在控制台上
        // 方式1:
        /*int data = fr.read();
        while(data != -1) {
            System.out.print((char)data);
            data = fr.read();
        }
        System.out.println();*/

        // 方式2:
        int data = -1;
        while ((data = fr.read()) != -1) {
            System.out.print((char) data);
        }
        System.out.println();

        // 4、流资源的关闭操作 (必须要关闭，否则会内存泄漏。)
        fr.close();
    }

    /**
     * 需求: 读取文件 D:\HeJing_Java\io_test\hello.txt 中的内容
     * 使用 try-catch-finally的方式处理异常，确保流一定可以关闭，避免内存泄漏。
     */
    @Test
    public void test02() {
        FileReader fr = null;

        try {
            // 1、创建File类的对象，对应着hello.txt文件
            File file = new File("D:\\HeJing_Java\\io_test\\hello.txt");
            // 2、创建输入型的字符流，用于读取数据。
            fr = new FileReader(file);
            // 3、读取数据，并显示在控制台上
            // 方式1:
        /*int data = fr.read();
        while(data != -1) {
            System.out.print((char)data);
            data = fr.read();
        }
        System.out.println();*/

            // 方式2:
            int data = -1;
            while ((data = fr.read()) != -1) {
                System.out.print((char) data);
            }
            System.out.println();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4、流资源的关闭操作 (必须要关闭，否则会内存泄漏。)
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 需求: 读取文件 D:\HeJing_Java\io_test\hello.txt 中的内容
     * 使用 try-catch-finally的方式处理异常，确保流一定可以关闭，避免内存泄漏。
     * <p>
     * --> 升级操作：
     * 对test02进行优化，每次读取多个字符存放到字符数组中，减少与磁盘交互的次数，提升效率。
     */
    @Test
    public void test03() {
        FileReader fr = null;

        try {
            // 1、创建File类的对象，对应着hello.txt文件
            File file = new File("D:\\HeJing_Java\\io_test\\hello.txt");
            // 2、创建输入型的字符流，用于读取数据。
            fr = new FileReader(file);

            // 3、读取数据，并显示在控制台上
            char[] cbuffer = new char[5];
            int size = -1;
            while ((size = fr.read(cbuffer)) != -1) {
                // 遍历数组
                for (int i = 0; i < size; i++) {
                    System.out.print(cbuffer[i]);
                }
            }
            System.out.println();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4、流资源的关闭操作 (必须要关闭，否则会内存泄漏。)
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 需求: 将内存中的数据写出到指定的文件中
     *
     */
    @Test
    public void test04() {
        FileWriter fw = null;

        try {
            // 1、创建File对象，指明要写出的文件的名称。
            File file = new File("D:\\HeJing_Java\\io_test\\info.txt");

            // 2、创建输出流
            // fw = new FileWriter(file); // 或者 fw = new FileWriter(file, append: false); 不追加，文件覆盖操作
            fw = new FileWriter(file, true);  // 现有文件追加写操作。

            // 3、写出的具体过程
            // 输出的方法: write(String str)  / write(char[] chardata)
            fw.write("I love you\n");
            fw.write("You love him\n");
            fw.write("...\n");
            System.out.println("输出成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 4、关闭流资源
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 需求: 复制一份hello.txt文件，命名为 hello_copy.txt文件
     */
    @Test
    public void test05(){
        FileReader fr = null;
        FileWriter fw = null;

        try {
            // 1、创建File对象，指明待复制的文件的路径以及 复制的目的文件路径
            File file_src = new File("D:\\HeJing_Java\\io_test\\hello.txt");
            File file_copy = new File("D:\\HeJing_Java\\io_test\\hello_copy.txt");

            // 2、创建输入流、输出流对象
            fr = new FileReader(file_src);
            fw = new FileWriter(file_copy);

            // 3、读取待复制文件的内容:
            int size = -1;
            char[] cbuffer = new char[5];
            while((size = fr.read(cbuffer)) != -1) {
                // 4、将读取到的内容保存到指定的文件中
                // 方式1:
                /*char[] buffer = new char[size];
                for(int i = 0; i < size; i++) {
                    buffer[i] = cbuffer[i];
                }
                fw.write(buffer);*/

                // 方式2: 与方式1一样
                // write(char[] cbuffer, int fromIndex, int len)
                fw.write(cbuffer, 0, size);
            }

            System.out.println("复制成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5、关闭流资源
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 需求: 复制一份p1.png文件，命名为p1_copy.png文件
     * 使用FileReader / FileWriter， 复制失败，因为字符流不适合用来进行图片、视频等的读写操作。
     */
    @Test
    public void test06(){
        FileReader fr = null;
        FileWriter fw = null;

        try {
            // 1、创建File对象，指明待复制的文件的路径以及 复制的目的文件路径
            File file_src = new File("D:\\HeJing_Java\\io_test\\image_test\\p1.png");
            File file_copy = new File("D:\\HeJing_Java\\io_test\\image_test\\p1_copy.png");

            // 2、创建输入流、输出流对象
            fr = new FileReader(file_src);
            fw = new FileWriter(file_copy);

            // 3、读取待复制文件的内容:
            int size = -1;
            char[] cbuffer = new char[5];
            while((size = fr.read(cbuffer)) != -1) {
                // 4、将读取到的内容保存到指定的文件中
                // 方式1:
                /*char[] buffer = new char[size];
                for(int i = 0; i < size; i++) {
                    buffer[i] = cbuffer[i];
                }
                fw.write(buffer);*/

                // 方式2: 与方式1一样
                // write(char[] cbuffer, int fromIndex, int len)
                fw.write(cbuffer, 0, size);
            }

            System.out.println("复制成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5、关闭流资源
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

























